// @const
const PROTOCOL_RESOURCES: string = "resources://";

/**
 * 自定义资源加载器
 */
export default class MyResLoader {
    /**
     * 私有化类默认构造器
     */
    private constructor() {
    }

    /**
     * 加载本地资源
     * 
     * @param strURL URL 地址
     * @param funOnComplete 加载完成回调函数
     */
    public static loadLocalRes(strURL: string, funOnComplete: (oAsset: cc.Asset) => void): void {
        // 确保回调函数不为空
        funOnComplete = funOnComplete || function () {
        };

        if (null == strURL ||
            "" == strURL) {
            funOnComplete(null);
            return;
        }

        if (strURL.startsWith(PROTOCOL_RESOURCES)) {
            strURL = strURL.substr(PROTOCOL_RESOURCES.length);
        }

        console.log("准备加载本地资源, URL = " + strURL);
        cc.resources.load(strURL, (oError, oAsset) => {
            if (null != oError) {
                console.log(oError);
                return;
            }

            console.log("加载本地资源完成, URL = " + strURL);
            funOnComplete(oAsset);
        });
    }

    /**
     * 加载本地资源数组, 也就是 resources 目录中的内容
     * 
     * @param oURLColl URL 地址集合
     * @param funOnComplete 加载完成回调函数
     */
    public static loadLocalResArray(
        oURLColl: Array<string> | Set<string>,
        funOnComplete: (oAssetMap: Map<string, cc.Asset>) => void): void {
        // 确保回调函数不为空
        funOnComplete = funOnComplete || function () {
        };

        if (null == oURLColl) {
            funOnComplete(null);
            return;
        }

        // 获取迭代器
        let oIter: IterableIterator<any> = oURLColl.entries();
        // 创建资产字典
        let oAssetMap: Map<string, cc.Asset> = new Map();

        let funLoadOneByOne = () => {
            // 获取迭代结果
            let oItResult: IteratorResult<string> = oIter.next();

            if (oItResult.done) {
                // 资源全部加载完成
                funOnComplete(oAssetMap);
                return;
            }

            let strURL: string = oItResult.value[1/*valueIndex*/];

            if (null == strURL ||
                "" == strURL ||
                oAssetMap.has(strURL)) {
                funLoadOneByOne();
                return;
            }

            MyResLoader.loadLocalRes(strURL, (oAsset) => {
                if (null != oAsset) {
                    // 添加资源到字典
                    oAssetMap.set(strURL, oAsset);
                }

                funLoadOneByOne();
            });
        };

        funLoadOneByOne();
    }

    /**
     * 加载远程资源
     * 
     * @param strURL URL 地址
     * @param funOnComplete 加载完成回调函数
     */
    public static loadRemoteRes(strURL: string, funOnComplete: (oAsset: cc.Asset) => void): void {
        // 确保回调函数不为空
        funOnComplete = funOnComplete || function () {
        };

        if (null == strURL ||
            "" == strURL) {
            funOnComplete(null);
            return;
        }

        console.log("准备加载远程资源, URL = " + strURL);
        cc.assetManager.loadRemote(strURL, (oError, oAsset) => {
            if (null != oError) {
                console.log(oError);
                return;
            }

            console.log("加载远程资源完成, URL = " + strURL);
            funOnComplete(oAsset);
        });
    }

    /**
     * 加载远程资源数组
     * 
     * @param oURLColl URL 地址数组
     * @param funOnComplete 加载完成回调函数
     */
    public static loadRemoteResArray(
        oURLColl: Array<string> | Set<string>,
        funOnComplete: (oAssetMap: Map<string, cc.Asset>) => void): void {
        // 确保回调函数不为空
        funOnComplete = funOnComplete || function () {
        };

        if (null == oURLColl) {
            funOnComplete(null);
            return;
        }

        // 获取迭代器
        let oIter: IterableIterator<any> = oURLColl.entries();
        // 创建资产字典
        let oAssetMap: Map<string, cc.Asset> = new Map();

        let funLoadOneByOne = () => {
            // 获取迭代结果
            let oItResult: IteratorResult<string> = oIter.next();

            if (oItResult.done) {
                // 资源全部加载完成
                funOnComplete(oAssetMap);
                return;
            }

            let strURL: string = oItResult.value[1/*valueIndex*/];

            if (null == strURL || 
                "" == strURL ||
                oAssetMap.has(strURL)) {
                funLoadOneByOne();
                return;
            }

            MyResLoader.loadRemoteRes(strURL, (oAsset) => {
                if (null != oAsset) {
                    // 添加资源到字典
                    oAssetMap.set(strURL, oAsset);
                }

                funLoadOneByOne();
            });
        };

        funLoadOneByOne();
    }

    /**
     * 加载本地或者远程资源数组
     * 
     * @param oURLColl URL 地址集合
     * @param funOnComplete 加载完成回调函数
     */
    public static loadMixedResArray(
        oURLColl: Array<string> | Set<string>,
        funOnComplete: (oAssetMap: Map<string, cc.Asset>) => void): void {
        // 确保回调函数不为空
        funOnComplete = funOnComplete || function () {
        };

        if (null == oURLColl) {
            funOnComplete(null);
            return;
        }

        // 获取迭代器
        let oIter: IterableIterator<any> = oURLColl.entries();
        // 创建资产字典
        let oAssetMap: Map<string, cc.Asset> = new Map();

        let funLoadOneByOne = () => {
            // 获取迭代结果
            let oItResult: IteratorResult<string> = oIter.next();

            if (oItResult.done) {
                // 资源全部加载完成
                funOnComplete(oAssetMap);
                return;
            }

            let strURL: string = oItResult.value[1/*valueIndex*/];

            if (null == strURL || 
                "" == strURL || 
                oAssetMap.has(strURL)) {
                funLoadOneByOne();
                return;
            }

            if (strURL.startsWith("resources://")) {
                MyResLoader.loadLocalRes(strURL, (oAsset) => {
                    // 添加资源到字典
                    oAssetMap.set(strURL, oAsset);
                    funLoadOneByOne();
                });
            }
            else {
                MyResLoader.loadRemoteRes(strURL, (oAsset) => {
                    // 添加资源到字典
                    oAssetMap.set(strURL, oAsset);
                    funLoadOneByOne();
                });
            }
        };

        funLoadOneByOne();
    }
}
